home *** CD-ROM | disk | FTP | other *** search
/ PsL Monthly 1993 December / PSL Monthly Shareware CD-ROM (December 1993).iso / prgmming / dos / c / stdlib1.exe / lha / SCANF.ASM < prev    next >
Assembly Source File  |  1990-06-25  |  11KB  |  525 lines

  1. stdlib        segment    para public 'slcode'
  2.         assume    cs:stdlib
  3.     extrn sl_print:far,sl_putw:far, sl_putcr:far
  4. print    macro
  5.  call sl_print
  6.   endm
  7. ;
  8.         extrn    sl_gets:far, sl_free:far, sl_atoi2:far
  9.         extrn    sl_atou2:far, sl_atol2:far, sl_atoul2:far
  10.         extrn    sl_atoh2:far
  11. ;
  12. ;
  13. ; Scanf- Like the "C" routine by the same name.  Calling sequence:
  14. ;
  15. ;               call    scanf
  16. ;               db      "format string",0
  17. ;               dd      item1, item2, ..., itemn
  18. ;
  19. ; The format string is identical to "C".  Item1..Itemn are pointers to
  20. ; values to print for this string.  Each item must be matched by the
  21. ; corresponding "%xxx" item in the format string.
  22. ;
  23. ; Format string format:
  24. ;
  25. ; 1)    If a non-whitespace character in the format string matches the next
  26. ;    input character, scanf eats that input character;  otherwise scanf
  27. ;    ignores the character in the format string.  If any whitespace char-
  28. ;    acter appears, scanf ignores all leading whitespace characters (new-
  29. ;    line not included) before an item.  If there is no whitespace on the
  30. ;    input, scanf ignores the whitespace characters in the input stream.
  31. ;
  32. ; 2)    Format Control Strings:
  33. ;
  34. ;    General format:  "%^f" where:
  35. ;
  36. ;                ^ = ^
  37. ;                f = a format character
  38. ;
  39. ;            The "^" is optional.
  40. ;
  41. ;    ^ present    The address associated with f is the address of a
  42. ;                pointer to the object, not the address of
  43. ;                the object itself.  The pointer is a far ptr.
  44. ;
  45. ;    f is one of the following
  46. ;
  47. ;        d -    Read a signed integer in decimal notation.
  48. ;        i -    Read a signed integer in decimal notation.
  49. ;        x -    Read a word value in hexadecimal notation.
  50. ;        h -    Read a byte value in hexadecimal notation.
  51. ;        u -    Read an unsigned integer in decimal notation.
  52. ;        c -    Read a character.
  53. ;        s -    Read a string.
  54. ;
  55. ;        ld-    Read a long signed integer.
  56. ;        li-    Read a long signed integer.
  57. ;        lx-    Read a long hexadecimal number.
  58. ;        lu-    Read a long unsigned number.
  59. ;
  60. ;
  61. ;    Calling Sequence:
  62. ;
  63. ;        call    Scanf
  64. ;        db    "Format String",0
  65. ;        dd    adrs1, adrs2, ..., adrsn
  66. ;
  67. ;    Where the format string is ala "C" (and the descriptions above)
  68. ;    and adrs1..adrsn are addresses (far ptr) to the items to print.
  69. ;    Unless the "^" modifier is present, these addresses are the actual
  70. ;    addresses of the objects to print.
  71. ;
  72. ; Note: Scanf always calls GETS to read a new string from the standard
  73. ;    input device.  Reading a string variable always reads all input
  74. ;    from the current position to the end of the current line.
  75. ;
  76. ;
  77. cr        equ    0dh
  78. ff        equ    0ch
  79. lf        equ    0ah
  80. tab        equ    09h
  81. bs        equ    08h
  82. ;
  83. RtnAdrs        equ    2[bp]
  84. OprndPtr    equ    -4[bp]
  85. InputPtr    equ    -8[bp]
  86. InpIndex    equ    -10[bp]
  87. ;
  88.         public  sl_scanf
  89. sl_scanf    proc    far
  90. ;
  91. ; Read a line from the standard input and save away a pointer to it.
  92. ;
  93.         push    bp
  94.         mov    bp, sp
  95.         sub    sp, 10            ;Save ptr to operands here.
  96.         pushf
  97.         push    ax
  98.         push    bx
  99.         push    cx
  100.         push    dx
  101.         push    di
  102.         push    si
  103.         push    es
  104.         push    ds
  105. ;
  106.         call    sl_gets
  107.         call    scanf
  108.         les    di, InputPtr
  109.         call    sl_free
  110.         mov    di, OprndPtr
  111.         mov    RtnAdrs, di    ;Put out new return address.
  112. ;
  113.         pop    ds
  114.         pop    es
  115.         pop    si
  116.         pop    di
  117.         pop    dx
  118.         pop    cx
  119.         pop    bx
  120.         pop    ax
  121.         popf
  122.         mov    sp, bp        ;Remove local variables.
  123.         pop    bp
  124.         ret
  125. ;
  126. sl_scanf    endp
  127. ;
  128. ;
  129. ; SSCANF-    Just like SCANF except you pass a pointer to the data
  130. ;        string in es:di rather than having scanf read it from
  131. ;        the keyboard.
  132. ;
  133.         public    sl_sscanf
  134. sl_sscanf    proc    far
  135.         push    bp
  136.         mov    bp, sp
  137.         sub    sp, 10            ;Save ptr to operands here.
  138.         pushf
  139.         push    ax
  140.         push    bx
  141.         push    cx
  142.         push    dx
  143.         push    di
  144.         push    si
  145.         push    es
  146.         push    ds
  147. ;
  148.         call    scanf
  149.         mov    di, OprndPtr
  150.         mov    RtnAdrs, di    ;Put out new return address.
  151. ;
  152.         pop    ds
  153.         pop    es
  154.         pop    si
  155.         pop    di
  156.         pop    dx
  157.         pop    cx
  158.         pop    bx
  159.         pop    ax
  160.         popf
  161.         mov    sp, bp        ;Remove local variables.
  162.         pop    bp
  163.         ret
  164. sl_sscanf    endp
  165. ;
  166. ;
  167. ; "Guts" of the scanf routines.
  168. ;
  169. scanf        proc    near
  170.         mov    InputPtr+2, es        ;Sock away ptr to string.
  171.         mov    InputPtr, di
  172.         mov    word ptr InpIndex, 0
  173. ;
  174. ;
  175. ; Get pointers to the return address (format string).
  176. ;
  177.         cld
  178.         les    di, RtnAdrs
  179.         lds    si, RtnAdrs
  180. ;
  181. ; Okay, search for the end of the format string.  After these instructions,
  182. ; di points just beyond the zero byte at the end of the format string.  This,
  183. ; of course, points at the first address beyond the format string.
  184. ;
  185.         mov    al, 0
  186.         mov    cx, 65535
  187.     repne    scasb
  188.         mov     OprndPtr, di
  189.         mov    OprndPtr+2, es
  190. ;
  191. ScanItems:      lodsb            ;Get char si points at.
  192. ScanItems2:    cmp    al, 0        ;EOS?
  193.         jz    ScanfDone
  194.         cmp    al, "%"        ;Start of a format string?
  195.         jz    FmtItem
  196. SkipIt:        cmp    al, " "
  197.         jz    SkipWS
  198.         les    di, InputPtr
  199.         mov    bx, InpIndex
  200.         cmp    al, es:[di][bx]
  201.         jnz    ScanItems
  202.         inc    word ptr InpIndex
  203.         jmp    ScanItems
  204. ;
  205. SkipWS:        les    di, InputPtr
  206.         mov    bx, InpIndex
  207. SkipWSLp:    cmp    byte ptr es:[di][bx], ' '
  208.         jnz    DoneSkip
  209.         inc    bx
  210.         jmp    SkipWSLp
  211. ;
  212. DoneSkip:    mov    InpIndex, bx
  213. Skip2:        lodsb
  214.         cmp    al, ' '            ;Skip additional whitespace
  215.         jz    Skip2            ; in the format string.
  216.         dec    si
  217.         jmp    ScanItems
  218. ;
  219. ;
  220. FmtItem:    call    GetFmtItem    ;Process the format item here.
  221.         jmp    ScanItems
  222. ;
  223. ;
  224. ScanfDone:        ret
  225. scanf        endp
  226. ;
  227. ;
  228. ;
  229. ; If we just saw a "%", come down here to handle the format item.
  230. ;
  231. GetFmtItem    proc    near
  232. ;
  233.         lodsb                ;Get char beyond "%"
  234. ;
  235. ; See if the user wants to specify a handle rather than a straight pointer
  236. ;
  237.         cmp    al, '^'
  238.         jne     ChkFmtChars
  239.         mov    ah, al
  240.         lodsb                ;Skip "^" character
  241. ;
  242. ; Okay, process the format characters down here.
  243. ;
  244. ChkFmtChars:    and    al, 05fh        ;l.c. -> U.C.
  245.         cmp    al, 'D'
  246.         je    GetDec
  247.         cmp    al, 'I'
  248.         je    GetDec
  249.         cmp    al, 'C'
  250.         je    GetChar
  251. ;
  252.         cmp    al, 'X'
  253.         jne    TryH
  254.         jmp    GetHexWord
  255. ;
  256. TryH:        cmp    al, 'H'
  257.         jne    TryU
  258.         jmp    GetHexByte
  259. ;
  260. TryU:        cmp    al, 'U'
  261.         jne    TryString
  262.         jmp    GetUDec
  263. ;
  264. TryString:    cmp    al, 'S'
  265.         jne    TryLong
  266.         jmp    GetString
  267. ;
  268. TryLong:    cmp    al, 'L'
  269.         jne    Default
  270. ;
  271. ; If we've got the "L" modifier, this is a long value to print, get the
  272. ; data type character as the next value:
  273. ;
  274.         lodsb
  275.         and    al, 05fh        ;l.c. -> U.C.
  276.         cmp    al, 'D'
  277.         je    JmpDec
  278.         cmp    al, 'I'
  279.         jne    TryLU
  280. JmpDec:        jmp    LongDec
  281. ;
  282. TryLU:        cmp    al, 'U'
  283.         jne    Default
  284.         jmp    LongU
  285. ;
  286. ;
  287. ;
  288. ; If none of the above, simply return without printing anything.
  289. ;
  290. Default:    ret
  291. ;
  292. ;
  293. ;
  294. ;
  295. ;
  296. ; Get a signed decimal value here.
  297. ;
  298. GetDec:        call    GetPtr            ;Get next pointer into ES:BX
  299.         push    ax            ;Save possible "^" char in ah
  300.         push    es
  301.         les    di, InputPtr
  302.         add    di, InpIndex        ;Point SI at integer.
  303.         cmp    byte ptr es:[di], 0    ;At end of string?
  304.         jz    QuitGetDec
  305.         call    sl_atoi2        ;Convert to integer in AX.
  306.         sub    di, InputPtr
  307.         mov    InpIndex, di
  308.         pop    es                 ; Ignore overflow or error.
  309.         mov    es:[bx], ax
  310. ;
  311.         pop    ax
  312.         ret
  313. ;
  314. QuitGetDec:    pop    es
  315.         pop    ax
  316.         ret                ;We're done!
  317. ;
  318. ;
  319. ;
  320. ; Print a character variable here.
  321. ;
  322. GetChar:    call    GetPtr            ;Get next pointer into ES:BX
  323.         push    ax            ;Save possible "^" char in ah
  324.         push    es
  325.         les    di, InputPtr
  326.         add    di, InpIndex        ;Point SI at char.
  327.         mov    al, es:[di]        ;Get char
  328.         cmp    al, 0            ;See if at EOS.
  329.         jz    QuitGetChar
  330.         inc    word ptr InpIndex    ;Bump up index.
  331.         pop    es             
  332.         mov    es:[bx], al
  333. ;
  334.         pop    ax
  335.         ret
  336. ;
  337. QuitGetChar:    pop    es
  338.         pop    ax
  339.         ret                ;We're done!
  340. ;
  341. ;
  342. ;
  343. ; Print a hexadecimal word value here.
  344. ;
  345. GetHexWord:    call    GetPtr            ;Get next pointer into ES:BX
  346.         push    ax            ;Save possible "^" char in ah
  347.         push    es
  348.         les    di, InputPtr
  349.         add    di, InpIndex        ;Point SI at integer.
  350.         cmp    byte ptr es:[di], 0    ;Check for EOS
  351.         jz    QuitGetHexWord
  352.         call    sl_atoh2        ;Convert to integer in AX.
  353.         sub    di, InputPtr
  354.         mov    InpIndex, di
  355.         pop    es                 ; Ignore overflow or error.
  356.         mov    es:[bx], ax
  357. ;
  358.         pop    ax
  359.         ret
  360. ;
  361. QuitGetHexWord:    pop    es
  362.         pop    ax
  363.         ret                ;We're done!
  364. ;
  365. ;
  366. ;
  367. ;
  368. ; Print hex bytes here.
  369. ;
  370. ;
  371. GetHexByte:    call    GetPtr            ;Get next pointer into ES:BX
  372.         push    ax            ;Save possible "^" char in ah
  373.         push    es
  374.         les    di, InputPtr
  375.         add    di, InpIndex        ;Point SI at integer.
  376.         cmp    byte ptr es:[di], 0    ;Check for EOS.
  377.         jz    QuitGetHexByte
  378.         call    sl_atoh2        ;Convert to integer in AX.
  379.         sub    di, InputPtr
  380.         mov    InpIndex, di
  381.         pop    es                 ; Ignore overflow or error.
  382.         mov    es:[bx], al
  383. ;
  384.         pop    a